/* Copyright (c) 2025 Beijing Semidrive Technology Corporation
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** ************************************************************************************************
 * \file     Firewall.c                                                                       *
 * \brief    Semidrive Firewall Driver                                                                  *
 *                                                                                                 *
 **************************************************************************************************/

#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************************************
 *                                      Include header files                                       *
 **************************************************************************************************/
#include "irq.h"
#include "Firewall.h"
#include "Firewall_Dio_Ip.h"
#include "Firewall_Mac_Ip.h"
#include "Firewall_Mpc_Ip.h"
#include "Firewall_Ppc_Ip.h"

#if (defined(CFG_PLATFORM_MCAL))
#include "Firewall_Cfg.h"

#if(FIREWALL_DEV_ERROR_DETECT == STD_ON)
#include "Det.h"
#endif /* #if(FIREWALL_DEV_ERROR_DETECT == STD_ON) */
#if (FIREWALL_SAFETY_ENABLE == STD_ON)
#include "FuSaMcalReportError.h"
#endif /** #if (FIREWALL_SAFETY_ENABLE == STD_ON) */

#define FIREWALL_START_SEC_CODE
#include "Firewall_MemMap.h"
#endif /** #if (defined(CFG_PLATFORM_MCAL)) */

/***************************************************************************************************
 *                                  Global Function Declarations                                   *
 **************************************************************************************************/
/**
 * \brief Configure the firewall.
 *
 * Driver Module Initialization function.The Initialization function shall
 * initialize MAC/MPC/PPC/GPIO registers with the values of the structure
 * referenced by the parameter ConfigPtr.
 *
 * \param[in] ctrl the firewall instance.
 * \param[in] cfg  the configuration of the MAC/MPC/PPC/GPIO module.
 *
 * \return The result of the firewall initialization function
 * \details - return FIREWALL_E_OK : Initializa firewall success.
 *          - return error code : Please refer to Firewall_ErrStatus.
 */
lld_status_t Firewall_Init(Firewall_ControllerType *ctrl,
                            const Firewall_ConfigType *cfg)
{
    lld_status_t ret_val;

    /* #10 Check the parameters. */
    if ((NULL == ctrl) || (NULL == cfg))
    {
        ret_val = (lld_status_t)FIREWALL_E_NULL_POINTER;
    }
    /* #20 Check the status of Firewall driver. */
    else if (FIREWALL_UNINIT != ctrl->Firewall_InitStatus)
    {
        ret_val = (lld_status_t)FIREWALL_E_INIT;
    }
    /* #30 Initialize the Firewall module. */
    else
    {
        /* Clear interrupt controller and status. */
        Firewall_MacClearInterrupt(ctrl->macBaseAddr);
        Firewall_PpcClearInterrupt(ctrl->macBaseAddr);
        if (NULL != cfg->mpcCfgPtr)
        {
            Firewall_MpcClearInterrupt(ctrl->macBaseAddr,
                            cfg->mpcCfgPtr, cfg->mpcMemPortCfgNum);
        }

        /* Configure the Firewall MAC module. */
        ret_val = Firewall_MacConfigure(ctrl, cfg->macCfgPtr);
        /* Configure the Firewall MPC module. */
        if (((lld_status_t)FIREWALL_E_OK == ret_val) && (0U < cfg->mpcMemPortCfgNum))
        {
            ret_val = Firewall_MpcConfigure(
                ctrl, cfg->mpcCfgPtr, cfg->mpcMemPortCfgNum);
        } /* else not needed */

        /* Enter critical region. */
        LLD_ENTER_CRITIAL_AREA(ulcpsr);

        /* Configure the Firewall PPC IP. */
        if (((lld_status_t)FIREWALL_E_OK == ret_val) && (0U < cfg->ppcIpCfgNum))
        {
            ret_val = Firewall_PpcIpConfigure(
                ctrl, cfg->ppcIpCfgPtr, cfg->ppcIpCfgNum);
        } /* else not needed */

        /* Configure the Firewall PPC IP as default. */
        if (((lld_status_t)FIREWALL_E_OK == ret_val) && (0U < cfg->ppcBaseIpCfgNum))
        {
            ret_val = Firewall_PpcIpConfigure(
                ctrl, cfg->ppcBaseIpCfgPtr, cfg->ppcBaseIpCfgNum);
        } /* else not needed */

        /* Configure the Firewall PPC Region. */
        if (((lld_status_t)FIREWALL_E_OK == ret_val) && (0U < cfg->ppcAddrCfgNum))
        {
            ret_val = Firewall_PpcAddrConfigure(
                ctrl, cfg->ppcAddrCfgPtr, cfg->ppcAddrCfgNum);
        } /* else not needed */

        if(((lld_status_t)FIREWALL_E_OK == ret_val) && (0U < cfg->ppcIpCfgNum))
        {
            /* Enable register configuration compare for safety mechanism. */
            Firewall_PpcRegCompEnable(ctrl->macBaseAddr);
        } /* else not needed */

        /* Exit critical region. */
        LLD_EXIT_CRITIAL_AREA(ulcpsr);
        /* Configure the Firewall GPIO module. */
        if (((lld_status_t)FIREWALL_E_OK == ret_val) && (0U < cfg->dioCoreCfgNum))
        {
            ret_val = Firewall_DioRuleSpaceConfigure(cfg->dioRuleSpaceCfgPtr,
                                                            cfg->dioCoreCfgNum);
        } /* else not needed */

        /* #40 Update the status of firewall instance after initialization. */
        if ((lld_status_t)FIREWALL_E_OK == ret_val)
        {
            /* Save the pointer when initialization success. */
            ctrl->Firewall_ConfigPtr = cfg;
            /* Switch Firewall driver status as initialized. */
            ctrl->Firewall_InitStatus = FIREWALL_INIT;
#if (!defined(CFG_PLATFORM_MCAL))
            if (1U == ctrl->interruptEnable && ctrl->Firewall_Irq > 0U)
            {
                irq_attach(ctrl->Firewall_Irq, (irq_handler)Firewall_Ip_IrqHandler, ctrl);
                irq_enable(ctrl->Firewall_Irq);
            } /* else not needed */
#endif /* #if !defined(CFG_PLATFORM_MCAL) */
        } /* else not needed */
    }

#if (defined(CFG_PLATFORM_MCAL))
/* #50 Report error code to the system if the firewall initialization failed. */
#if ((FIREWALL_DEV_ERROR_DETECT == STD_ON) || (FIREWALL_SAFETY_ENABLE == STD_ON))
    if ((lld_status_t)FIREWALL_E_OK != ret_val)
    {
#if (FIREWALL_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)FIREWALL_MODULE_ID,
                                FIREWALL_INSTANCE_ID, FIREWALL_INIT_ID, ret_val);
#endif /* #if (FIREWALL_DEV_ERROR_DETECT == STD_ON) */
#if (FIREWALL_SAFETY_ENABLE == STD_ON)
        (void)FuSaMcal_ReportError((uint16)FIREWALL_MODULE_ID,
                                FIREWALL_INSTANCE_ID, FIREWALL_INIT_ID, ret_val);
#endif /** #if (FIREWALL_SAFETY_ENABLE == STD_ON) */
    } /* else not needed */
#endif /* #if ((FIREWALL_DEV_ERROR_DETECT == STD_ON) || (FIREWALL_SAFETY_ENABLE == STD_ON)) */
#endif /* #if defined(CFG_PLATFORM_MCAL) */

    return ret_val;
}

/**
 * \brief Deinitialize the firewall.
 *
 * This function change the firewall instance state to FIREWALL_UNINIT,
 * and disable the interrupt of the MPC and PPC module.
 * This function does not turn off permission detection,
 * and should only called by lowpower feature.
 *
 * \param[in] ctrl  the firewall instance.
 *
 * \return The result of the firewall deinitialization function
 * \details - return FIREWALL_E_OK : Initializa firewall success.
 *          - return error code : Please refer to Firewall_ErrStatus.
 */
lld_status_t Firewall_Deinit(Firewall_ControllerType *ctrl)
{
    lld_status_t ret_val = (lld_status_t)FIREWALL_E_OK;

    /* #10 Check the status of Firewall driver. */
    if (NULL == ctrl)
    {
        ret_val = (lld_status_t)FIREWALL_E_NULL_POINTER;
    }
    else if (FIREWALL_INIT != ctrl->Firewall_InitStatus)
    {
        ret_val = (lld_status_t)FIREWALL_E_UNINIT;
    }
    else
    {
        if (1U == ctrl->interruptEnable)
        {
            Firewall_MpcInterruptEnable(ctrl->macBaseAddr,
                    ctrl->Firewall_ConfigPtr->mpcCfgPtr,
                    ctrl->Firewall_ConfigPtr->mpcMemPortCfgNum, false);
            Firewall_PpcInterruptEnable(ctrl->macBaseAddr, false);
#if (!defined(CFG_PLATFORM_MCAL))
            if (ctrl->Firewall_Irq > 0U)
            {
                irq_detach(ctrl->Firewall_Irq);
                irq_disable(ctrl->Firewall_Irq);
            } /* else not needed */
#endif /* #if !defined(CFG_PLATFORM_MCAL) */
        }

        ctrl->Firewall_InitStatus = FIREWALL_UNINIT;
    }

#if (defined(CFG_PLATFORM_MCAL))
/* #20 Report error code to the system if the firewall deinit failed. */
#if ((FIREWALL_DEV_ERROR_DETECT == STD_ON) || (FIREWALL_SAFETY_ENABLE == STD_ON))
    if ((lld_status_t)FIREWALL_E_OK != ret_val)
    {
#if (FIREWALL_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)FIREWALL_MODULE_ID,
                                FIREWALL_INSTANCE_ID, FIREWALL_DEINIT_ID, ret_val);
#endif /* #if (FIREWALL_DEV_ERROR_DETECT == STD_ON) */
#if (FIREWALL_SAFETY_ENABLE == STD_ON)
        (void)FuSaMcal_ReportError((uint16)FIREWALL_MODULE_ID,
                                FIREWALL_INSTANCE_ID, FIREWALL_DEINIT_ID, ret_val);
#endif /** #if (FIREWALL_SAFETY_ENABLE == STD_ON) */
    } /* else not needed */
#endif /* #if ((FIREWALL_DEV_ERROR_DETECT == STD_ON) || (FIREWALL_SAFETY_ENABLE == STD_ON)) */
#endif /* #if defined(CFG_PLATFORM_MCAL) */

    return ret_val;
}

/**
 * \brief Assigns the master to the specified domain.
 *
 * Assigns the specified master to a domain.
 * This function should be executed after the initialization function
 * Firewall_Init().
 *
 * \param[in] ctrl  the firewall instance.
 * \param[in] master_id  the id of the master.
 * \param[in] domain_id  the id of the domain.
 *
 * \return The result of this function.
 * \details - return FIREWALL_E_OK, Assigned the master to the domain success.
 *          - return FIREWALL_E_UNINIT: The firewall is uninitialized.
 *          - return FIREWALL_E_MAC_MASTER_ID: The master id is unvalid.
 *          - return FIREWALL_E_MAC_DOMAIN_ID: The domain id is unvalid.
 *          - return FIREWALL_E_MAC_LOCKED: The domain assignment of the master
 *                                          is locked.
 */
lld_status_t Firewall_AssignDomain(const Firewall_ControllerType *ctrl, uint8_t master_id,
                                     uint8_t domain_id)
{
    lld_status_t ret_val;

    /* #10 Check the status of Firewall driver. */
    if (NULL == ctrl)
    {
        ret_val = (lld_status_t)FIREWALL_E_NULL_POINTER;
    }
    else if (FIREWALL_INIT != ctrl->Firewall_InitStatus)
    {
        ret_val = (lld_status_t)FIREWALL_E_UNINIT;
    }
    else
    {
        /* #20 Assign the master to the specified domain. */
        ret_val =
            Firewall_MacAssignDomain(ctrl->macBaseAddr, master_id, domain_id);
    }

#if (defined(CFG_PLATFORM_MCAL))
/* #30 Report error code to the system if the firewall assign domain failed. */
#if ((FIREWALL_DEV_ERROR_DETECT == STD_ON) || (FIREWALL_SAFETY_ENABLE == STD_ON))
    if ((lld_status_t)FIREWALL_E_OK != ret_val)
    {
#if (FIREWALL_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)FIREWALL_MODULE_ID,
                                FIREWALL_INSTANCE_ID, FIREWALL_ASSIGN_DOMAIN_ID, ret_val);
#endif /* #if (FIREWALL_DEV_ERROR_DETECT == STD_ON) */
#if (FIREWALL_SAFETY_ENABLE == STD_ON)
        (void)FuSaMcal_ReportError((uint16)FIREWALL_MODULE_ID,
                                FIREWALL_INSTANCE_ID, FIREWALL_ASSIGN_DOMAIN_ID, ret_val);
#endif /** #if (FIREWALL_SAFETY_ENABLE == STD_ON) */
    } /* else not needed */
#endif /* #if ((FIREWALL_DEV_ERROR_DETECT == STD_ON) || (FIREWALL_SAFETY_ENABLE == STD_ON)) */
#endif /* #if defined(CFG_PLATFORM_MCAL) */

    return ret_val;
}

/**
 * \brief Lock the domain assignment of the master.
 *
 * This function lock the domain assignment of the master, should be called
 * after the initialization function Firewall_Init() or domain assignment
 * function Firewall_AssignDomain().
 *
 * \param[in] ctrl  the firewall instance.
 *
 * \return The result of this function.
 * \details - return FIREWALL_E_OK : Lock domain assignment success.
 *          - return FIREWALL_E_INIT : The firewall is uninitialized.
 *          - return FIREWALL_E_NULL_POINTER : The pointer to the MAC
 * configuration is NULL.
 */
lld_status_t Firewall_LockDomainAssignment(const Firewall_ControllerType *ctrl)
{
    lld_status_t ret_val = (lld_status_t)FIREWALL_E_OK;

    /* #10 Check the status of Firewall driver. */
    if (NULL == ctrl)
    {
        ret_val = (lld_status_t)FIREWALL_E_NULL_POINTER;
    }
    else if (FIREWALL_INIT != ctrl->Firewall_InitStatus)
    {
        ret_val = (lld_status_t)FIREWALL_E_UNINIT;
    }
    else
    {
        /* #20 Lock the domain assignment of the master. */
        Firewall_MacLockDomainAssignment(ctrl->macBaseAddr);
    }

#if (defined(CFG_PLATFORM_MCAL))
/* #30 Report error code to the system if the firewall lock domain failed. */
#if ((FIREWALL_DEV_ERROR_DETECT == STD_ON) || (FIREWALL_SAFETY_ENABLE == STD_ON))
    if ((lld_status_t)FIREWALL_E_OK != ret_val)
    {
#if (FIREWALL_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)FIREWALL_MODULE_ID,
                                FIREWALL_INSTANCE_ID, FIREWALL_LOCK_DOMAIN_ID, ret_val);
#endif /* #if (FIREWALL_DEV_ERROR_DETECT == STD_ON) */
#if (FIREWALL_SAFETY_ENABLE == STD_ON)
        (void)FuSaMcal_ReportError((uint16)FIREWALL_MODULE_ID,
                                FIREWALL_INSTANCE_ID, FIREWALL_LOCK_DOMAIN_ID, ret_val);
#endif /** #if (FIREWALL_SAFETY_ENABLE == STD_ON) */
    } /* else not needed */
#endif /* #if ((FIREWALL_DEV_ERROR_DETECT == STD_ON) || (FIREWALL_SAFETY_ENABLE == STD_ON)) */
#endif /* #if defined(CFG_PLATFORM_MCAL) */

    return ret_val;
}

/**
 * \brief Set callback function for firewall.
 *
 * \param[in] ctrl  the firewall instance.
 * \param[in] callback  the callback function.
 * \param[in] userdata  the param of callback function.
 *
 * \return The result of this function.
 * \details - return FIREWALL_E_OK : Set callback function success.
 *          - return FIREWALL_E_NULL_POINTER : The pointer to the MAC
 * configuration is NULL.
 *          - return FIREWALL_E_UNINIT : The firewall is uninitialized.
 */
lld_status_t Firewall_SetCallback(Firewall_ControllerType *ctrl,
                                    sdrv_firewall_callback_t callback,
                                    void *userdata)
{
    lld_status_t ret_val = (lld_status_t)FIREWALL_E_OK;
    /* #10 Check the parameters. */
    if (NULL == ctrl)
    {
        ret_val = (lld_status_t)FIREWALL_E_NULL_POINTER;
    }
    /* #20 Check the status of Firewall driver. */
    else if (FIREWALL_INIT != ctrl->Firewall_InitStatus)
    {
        ret_val = (lld_status_t)FIREWALL_E_UNINIT;
    }
    /* #30 Store the callback function and user's data. */
    else
    {
        ctrl->callback = callback;
        ctrl->userdata = userdata;
    }

#if (defined(CFG_PLATFORM_MCAL))
/* #40 Report error code to the system if the firewall set callback func failed. */
#if ((FIREWALL_DEV_ERROR_DETECT == STD_ON) || (FIREWALL_SAFETY_ENABLE == STD_ON))
    if ((lld_status_t)FIREWALL_E_OK != ret_val)
    {
#if (FIREWALL_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)FIREWALL_MODULE_ID,
                                FIREWALL_INSTANCE_ID, FIREWALL_SET_CALLBACK_ID, ret_val);
#endif /* #if (FIREWALL_DEV_ERROR_DETECT == STD_ON) */
#if (FIREWALL_SAFETY_ENABLE == STD_ON)
        (void)FuSaMcal_ReportError((uint16)FIREWALL_MODULE_ID,
                                FIREWALL_INSTANCE_ID, FIREWALL_SET_CALLBACK_ID, ret_val);
#endif /** #if (FIREWALL_SAFETY_ENABLE == STD_ON) */
    } /* else not needed */
#endif /* #if ((FIREWALL_DEV_ERROR_DETECT == STD_ON) || (FIREWALL_SAFETY_ENABLE == STD_ON)) */
#endif /* #if defined(CFG_PLATFORM_MCAL) */

    return ret_val;
}

/**
 * \brief Handle firewall interrupt.
 *
 * This function clear MAC/PPC/MPC Interruption, return interrupt state.
 *
 * \param [in] irq the irq number of the firewall.
 * \param [in] ctrl sdrv firewall controller.
 *
 * \return The result of this function.
 * \details - return 0 : Handle firewall interrupt success.
 *          - return 1 : The pointer to the MAC configuration is NULL.
 *          - return 2 : The firewall is uninitialized.
 */
int32_t Firewall_Ip_IrqHandler(uint32_t irq, void *ctrl)
{
    lld_status_t ret_val;
    Firewall_ControllerType *firewall_ctrl = (Firewall_ControllerType *)ctrl;
    Firewall_PpcIrqStaType ppc_irq_sta;
    Firewall_MpcIrqStaType mpc_irq_sta = {0U};

    /* #10 Check if the interrupt is valid (EN_FUSALIB needs to be defined). */
    irq_log_check_valid(irq);

    /* #20 Check the parameters. */
    if (NULL == ctrl)
    {
        ret_val = (lld_status_t)FIREWALL_E_NULL_POINTER;
    }
    /* #30 Check the status of Firewall driver. */
    else if (FIREWALL_INIT != firewall_ctrl->Firewall_InitStatus)
    {
        ret_val = (lld_status_t)FIREWALL_E_UNINIT;
        Firewall_PpcClearInterrupt(firewall_ctrl->macBaseAddr);
        if (NULL != firewall_ctrl->Firewall_ConfigPtr)
        {
            Firewall_MpcClearInterrupt(firewall_ctrl->macBaseAddr,
                firewall_ctrl->Firewall_ConfigPtr->mpcCfgPtr,
                firewall_ctrl->Firewall_ConfigPtr->mpcMemPortCfgNum);
        }
    }
    /* #40 Check the status of MPC and PPC module. */
    else
    {
        ppc_irq_sta = Firewall_PpcIrqHandler(firewall_ctrl->macBaseAddr);
        ret_val = Firewall_MpcIrqHandler(firewall_ctrl->macBaseAddr,
                        firewall_ctrl->Firewall_ConfigPtr->mpcCfgPtr,
                        firewall_ctrl->Firewall_ConfigPtr->mpcMemPortCfgNum,
                        &mpc_irq_sta);
        /* #41 Enter critical region. */
        LLD_ENTER_CRITIAL_AREA(ulcpsr);

        /* #42 Save the illegal access information. */
        firewall_ctrl->error_info.ppcErrInfo[ppc_irq_sta.ppcApbmuxId] =
            ppc_irq_sta;
        firewall_ctrl->error_info.mpcErrInfo[mpc_irq_sta.mpcMemPortId] =
            mpc_irq_sta;

        /* #43 Exit critical region. */
        LLD_EXIT_CRITIAL_AREA(ulcpsr);

        /* #44 Motify the user. */
        if ((NULL != firewall_ctrl->callback) &&
            ((0U != ppc_irq_sta.ppcErrSta) ||
             (0U != mpc_irq_sta.mpcErrSta)))
        {
            firewall_ctrl->callback(firewall_ctrl, firewall_ctrl->userdata);
        }
    }

    /* #50 Clear the interrupt of the MAC module. */
    Firewall_MacClearInterrupt(FIREWALL_APB_MAC_BASE);

    return (int32_t)ret_val;
}

/**
 * \brief Get firewall illegal access infomation.
 *
 * Should enable the macro FIREWALL_INTERRUPT_EN.
 *
 * \param[in] ctrl  the firewall instance.
 * \param[in] firewall_err_info  Pointer to the buffer used by system to get the
 * information.
 *
 * \return The result of this function.
 * \details - return FIREWALL_E_OK : Set callback function success.
 *          - return FIREWALL_E_NULL_POINTER : The pointer to the MAC
 * configuration is NULL.
 *          - return FIREWALL_E_UNINIT : The firewall is uninitialized.
 */
lld_status_t Firewall_GetErrorInformation(Firewall_ControllerType *ctrl,
                                      Firewall_ErrInfoType *firewall_err_info)
{
    lld_status_t ret_val = (lld_status_t)FIREWALL_E_OK;
    uint8_t port_num;
    uint16_t ip_num;

    /* #10 Check the parameters. */
    if ((NULL == ctrl) || (NULL == firewall_err_info))
    {
        ret_val = (lld_status_t)FIREWALL_E_NULL_POINTER;
    }
    /* #20 Check the status of Firewall driver. */
    else if (FIREWALL_INIT != ctrl->Firewall_InitStatus)
    {
        ret_val = (lld_status_t)FIREWALL_E_UNINIT;
    }
    else
    {
        /* #30 Enter critical region. */
        LLD_ENTER_CRITIAL_AREA(ulcpsr);

        /* #40 Get the illegal access information of the firewall from the
         * global variable. Clear the illegal access information of the firewall
         * in a global variable.
         */
        for (ip_num = 0U; ip_num < FIREWALL_PPC_APBMUX_MAXNUM; ++ip_num)
        {
            firewall_err_info->ppcErrInfo[ip_num] =
                ctrl->error_info.ppcErrInfo[ip_num];
            ctrl->error_info.ppcErrInfo[ip_num].ppcApbmuxId = 0U;
            ctrl->error_info.ppcErrInfo[ip_num].ppcErrSta = 0U;
        }
        for (port_num = 0U; port_num < FIREWALL_MPC_MEMPORT_MAXNUM; ++port_num)
        {
            firewall_err_info->mpcErrInfo[port_num] =
                ctrl->error_info.mpcErrInfo[port_num];
            ctrl->error_info.mpcErrInfo[port_num].mpcMemPortId = 0U;
            ctrl->error_info.mpcErrInfo[port_num].mpcErrSta = 0U;
        }

        /* Exit critical region. */
        LLD_EXIT_CRITIAL_AREA(ulcpsr);
    }

#if (defined(CFG_PLATFORM_MCAL))
/* #50 Report error code to the system if the firewall get error info failed. */
#if ((FIREWALL_DEV_ERROR_DETECT == STD_ON) || (FIREWALL_SAFETY_ENABLE == STD_ON))
    if ((lld_status_t)FIREWALL_E_OK != ret_val)
    {
#if (FIREWALL_DEV_ERROR_DETECT == STD_ON)
        (void)Det_ReportError((uint16)FIREWALL_MODULE_ID,
                                FIREWALL_INSTANCE_ID, FIREWALL_GET_ERRORINFO_ID, ret_val);
#endif /* #if (FIREWALL_DEV_ERROR_DETECT == STD_ON) */
#if (FIREWALL_SAFETY_ENABLE == STD_ON)
        (void)FuSaMcal_ReportError((uint16)FIREWALL_MODULE_ID,
                                FIREWALL_INSTANCE_ID, FIREWALL_GET_ERRORINFO_ID, ret_val);
#endif /** #if (FIREWALL_SAFETY_ENABLE == STD_ON) */
    } /* else not needed */
#endif /* #if ((FIREWALL_DEV_ERROR_DETECT == STD_ON) || (FIREWALL_SAFETY_ENABLE == STD_ON)) */
#endif /* #if defined(CFG_PLATFORM_MCAL) */

    return ret_val;
}

#if (defined(CFG_PLATFORM_MCAL))
#define FIREWALL_STOP_SEC_CODE
#include "Firewall_MemMap.h"
#endif /** #if (defined(CFG_PLATFORM_MCAL)) */

#ifdef __cplusplus
}
#endif

/* End of file */
